package cn.loioi.activiti;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.pagehelper.StringUtil;

@SuppressWarnings("unused")
public class ActivitiService {
	private final Logger logger = LoggerFactory.getLogger(ActivitiService.class);
	private static final boolean DEBUG = true;
	private TaskService taskService;
	private HistoryService historyService;
	private ProcessEngine processEngine;
	private RuntimeService runtimeService;
	private IdentityService identityService;
	private RepositoryService repositoryService;
	private ManagementService managementService;

	public ActivitiService() {
	}

	public TaskService getTaskService() {
		return taskService;
	}

	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

	public HistoryService getHistoryService() {
		return historyService;
	}

	public void setHistoryService(HistoryService historyService) {
		this.historyService = historyService;
	}

	public ProcessEngine getProcessEngine() {
		return processEngine;
	}

	public void setProcessEngine(ProcessEngine processEngine) {
		this.processEngine = processEngine;
	}

	public RuntimeService getRuntimeService() {
		return runtimeService;
	}

	public void setRuntimeService(RuntimeService runtimeService) {
		this.runtimeService = runtimeService;
	}

	public IdentityService getIdentityService() {
		return identityService;
	}

	public void setIdentityService(IdentityService identityService) {
		this.identityService = identityService;
	}

	public RepositoryService getRepositoryService() {
		return repositoryService;
	}

	public void setRepositoryService(RepositoryService repositoryService) {
		this.repositoryService = repositoryService;
	}

	public ManagementService getManagementService() {
		return managementService;
	}

	public void setManagementService(ManagementService managementService) {
		this.managementService = managementService;
	}

	/**
	 * 部署流程实例
	 * @param bpnmFilePath 流程文件路径
	 * @throws FileNotFoundException
	 */
	public void deploymentBpnmFile(String bpnmFilePath) throws FileNotFoundException {
		Deployment deployment = repositoryService.createDeployment().addInputStream(bpnmFilePath.substring(bpnmFilePath.lastIndexOf(File.separator) + 1, bpnmFilePath.length()), new FileInputStream(new File(bpnmFilePath))).deploy();
		if (DEBUG) logger.debug("流程已部署:processID is " + deployment.getId() + ",createTime is " + deployment.getDeploymentTime());
	}

	/**
	 * 部署流程实例
	 * @param resource 流程文件路径
	 * @throws FileNotFoundException
	 */
	public void deploymentClasspathResource(String resource) {
		Deployment deployment = repositoryService.createDeployment().addClasspathResource(resource).deploy();
		if (DEBUG) logger.debug("流程已部署:processID is " + deployment.getId() + ",createTime is " + deployment.getDeploymentTime());
	}

	/**
	 * 部署流程实例
	 * @param zipInputStream 流程文件路径
	 * @throws FileNotFoundException
	 */
	public void deploymentZipInputStream(ZipInputStream zipInputStream) {
		Deployment deployment = repositoryService.createDeployment().addZipInputStream(zipInputStream).deploy();
		if (DEBUG) logger.debug("流程已部署:processID is " + deployment.getId() + ",createTime is " + deployment.getDeploymentTime());
	}

	/**
	 * 启动流程
	 * @param processDefinitionId 流程部署KEY
	 * @param businessKey
	 * @param authenticatedUserId activiti:initiator的值
	 * @param variables 流程变量
	 * @return
	 */
	public ProcessInstance startProcessInstanceByKey(String processDefinitionId, String businessKey, String authenticatedUserId, Map<String, Object> variables) {
		if (StringUtils.isEmpty(authenticatedUserId)) identityService.setAuthenticatedUserId(authenticatedUserId);
		ProcessInstance processInstance = null;
		if (StringUtils.isNotEmpty(businessKey) && variables != null) {
			processInstance = runtimeService.startProcessInstanceById(processDefinitionId, businessKey, variables);
		} else if (variables != null) {
			processInstance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
		} else if (StringUtils.isNotEmpty(businessKey)) {
			processInstance = runtimeService.startProcessInstanceById(processDefinitionId, businessKey);
		} else {
			processInstance = runtimeService.startProcessInstanceByKey(processDefinitionId);
		}

		if (DEBUG) logger.debug("流程已启动：processDefinitionId -> {},businessKey -> {},authenticatedUserId -> {},process -> {}", processDefinitionId, businessKey, authenticatedUserId, processInstance.getId());
		return processInstance;
	}

	/**
	 * 启动流程
	 * @param processDefinitionId 流程部署KEY
	 * @param businessKey
	 * @param variables 流程变量
	 * @return
	 */
	public ProcessInstance startProcessInstanceByKey(String processDefinitionId, String businessKey, Map<String, Object> variables) {
		return startProcessInstanceByKey(processDefinitionId, businessKey, null, variables);
	}

	/**
	 * 启动流程
	 * @param processDefinitionId 流程部署KEY
	 * @param businessKey
	 * @return
	 */
	public ProcessInstance startProcessInstanceByKey(String processDefinitionId, String businessKey) {
		return startProcessInstanceByKey(processDefinitionId, businessKey, null, null);
	}

	/**
	 * 启动流程
	 * @param processDefinitionId 流程部署KEY
	 * @param variables 流程变量
	 * @return
	 */
	public ProcessInstance startProcessInstanceByKey(String processDefinitionId, Map<String, Object> variables) {
		return startProcessInstanceByKey(processDefinitionId, null, null, variables);
	}

	/**
	 * 启动流程
	 * @param processDefinitionId 流程部署KEY
	 * @return
	 */
	public ProcessInstance startProcessInstanceByKey(String processDefinitionId) {
		return startProcessInstanceByKey(processDefinitionId, null, null, null);
	}

	/**
	 * 查询Task
	 * @return
	 */
	public TaskQuery taskQuery() {
		return taskService.createTaskQuery();
	}

	/**
	 * 查询GroupTask列表
	 * @param userName
	 * @return
	 */
	public List<Task> queryGroupTaskList(String groupName) {
		List<Task> tasks = taskQuery().taskCandidateGroup(groupName).list();
		if (DEBUG) logger.debug("已查询到({})有{}条待处理任务!", groupName, tasks.size());
		return tasks;
	}

	/**
	 * 查询UserTask列表
	 * @param userName
	 * @return
	 */
	public List<Task> queryUserTaskList(String userName) {
		List<Task> tasks = taskQuery().taskCandidateOrAssigned(userName).list();
		if (DEBUG) logger.debug("已查询到({})有{}条待处理任务!", userName, tasks.size());
		return tasks;
	}

	/**
	 * 完成UTask
	 * @param taskId 任务ID
	 * @param proMap 流程变量
	 */
	public void completeTask(String taskId, Map<String, Object> proMap) {
		if (proMap != null) {
			taskService.complete(taskId, proMap);
		} else {
			taskService.complete(taskId);
		}
		logger.debug("任务({})已完成", taskId);
	}

}
